package org.ehe.finance.receipt.utils;

import cn.hutool.core.util.StrUtil;
import org.ehe.finance.receipt.constants.ReceiptConstants;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.regex.Pattern;

/**
 * 收款单工具类
 * @author :zhangnn
 * @className :ReceiptUtils
 * @description: TODO
 * @date 2025-09-02 15:34:36
 */
public class ReceiptUtils {
    private static final Pattern RECEIPT_NO_PATTERN = Pattern.compile(ReceiptConstants.Patterns.RECEIPT_NO_PATTERN);
    private static final Pattern AMOUNT_PATTERN = Pattern.compile(ReceiptConstants.Patterns.AMOUNT_PATTERN);

    /**
     * 生成收款单号
     * @param sequence 序列号
     * @return 收款单号
     */
    public static String generateReceiptNo(int sequence) {
        String datePart = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        return ReceiptConstants.RECEIPT_NO_PREFIX + datePart + String.format("%04d", sequence);
    }

    /**
     * 生成收款单号（指定日期）
     * @param date 日期
     * @param sequence 序列号
     * @return 收款单号
     */
    public static String generateReceiptNo(LocalDate date, int sequence) {
        String datePart = date.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        return ReceiptConstants.RECEIPT_NO_PREFIX + datePart + String.format("%04d", sequence);
    }

    /**
     * 验证收款单号格式
     * @param receiptNo 收款单号
     * @return 是否有效
     */
    public static boolean isValidReceiptNo(String receiptNo) {
        if (StrUtil.isBlank(receiptNo)) {
            return false;
        }
        return RECEIPT_NO_PATTERN.matcher(receiptNo.trim()).matches();
    }

    /**
     * 验证金额格式
     * @param amount 金额字符串
     * @return 是否有效
     */
    public static boolean isValidAmount(String amount) {
        if (StrUtil.isBlank(amount)) {
            return false;
        }
        return AMOUNT_PATTERN.matcher(amount.trim()).matches();
    }

    /**
     * 格式化金额（保留2位小数）
     * @param amount 金额
     * @return 格式化后的金额
     */
    public static BigDecimal formatAmount(BigDecimal amount) {
        if (amount == null) {
            return BigDecimal.ZERO;
        }
        return amount.setScale(2, RoundingMode.HALF_UP);
    }

    /**
     * 格式化汇率（保留4位小数）
     * @param rate 汇率
     * @return 格式化后的汇率
     */
    public static BigDecimal formatExchangeRate(BigDecimal rate) {
        if (rate == null) {
            return BigDecimal.ONE;
        }
        return rate.setScale(4, RoundingMode.HALF_UP);
    }

    /**
     * 计算外币金额
     * @param amount 本币金额
     * @param exchangeRate 汇率
     * @return 外币金额
     */
    public static BigDecimal calculateForeignAmount(BigDecimal amount, BigDecimal exchangeRate) {
        if (amount == null || exchangeRate == null) {
            return BigDecimal.ZERO;
        }
        return formatAmount(amount.divide(exchangeRate, 4, RoundingMode.HALF_UP));
    }

    /**
     * 计算本币金额
     * @param foreignAmount 外币金额
     * @param exchangeRate 汇率
     * @return 本币金额
     */
    public static BigDecimal calculateLocalAmount(BigDecimal foreignAmount, BigDecimal exchangeRate) {
        if (foreignAmount == null || exchangeRate == null) {
            return BigDecimal.ZERO;
        }
        return formatAmount(foreignAmount.multiply(exchangeRate));
    }

    /**
     * 获取收款类型描述
     * @param type 收款类型
     * @return 描述
     */
    public static String getReceiptTypeDesc(Integer type) {
        if (type == null) {
            return "未知";
        }
        switch (type) {
            case 1:
                return "销售收款";
            case 2:
                return "预收款";
            case 3:
                return "其他收款";
            default:
                return "未知";
        }
    }

    /**
     * 获取收款方式描述
     * @param method 收款方式
     * @return 描述
     */
    public static String getPaymentMethodDesc(Integer method) {
        if (method == null) {
            return "未知";
        }
        switch (method) {
            case 1:
                return "现金";
            case 2:
                return "银行转账";
            case 3:
                return "票据";
            case 4:
                return "其他";
            default:
                return "未知";
        }
    }

    /**
     * 获取状态描述
     * @param status 状态
     * @return 描述
     */
    public static String getStatusDesc(Integer status) {
        if (status == null) {
            return "未知";
        }
        switch (status) {
            case 1:
                return "未审核";
            case 2:
                return "已审核";
            default:
                return "未知";
        }
    }

    /**
     * 验证收款日期
     * @param receiptDate 收款日期
     * @return 是否有效
     */
    public static boolean isValidReceiptDate(LocalDate receiptDate) {
        if (receiptDate == null) {
            return false;
        }
        // 收款日期不能超过当前日期
        return !receiptDate.isAfter(LocalDate.now());
    }

    /**
     * 计算日期差（天数）
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 天数差
     */
    public static long daysBetween(LocalDate startDate, LocalDate endDate) {
        if (startDate == null || endDate == null) {
            return 0;
        }
        return Math.abs(startDate.until(endDate).getDays());
    }

    /**
     * 判断是否即将到期
     * @param receiptDate 收款日期
     * @param days 天数
     * @return 是否即将到期
     */
    public static boolean isDueSoon(LocalDate receiptDate, int days) {
        if (receiptDate == null) {
            return false;
        }
        LocalDate dueDate = LocalDate.now().plusDays(days);
        return receiptDate.isBefore(dueDate) || receiptDate.isEqual(dueDate);
    }

    /**
     * 清理字符串（去除空格和特殊字符）
     * @param str 原字符串
     * @return 清理后的字符串
     */
    public static String cleanString(String str) {
        if (StrUtil.isBlank(str)) {
            return "";
        }
        return str.trim().replaceAll("\\s+", " ");
    }

    /**
     * 截取字符串（超长时截断）
     * @param str 原字符串
     * @param maxLength 最大长度
     * @return 截取后的字符串
     */
    public static String truncateString(String str, int maxLength) {
        if (StrUtil.isBlank(str)) {
            return "";
        }
        String cleaned = cleanString(str);
        if (cleaned.length() <= maxLength) {
            return cleaned;
        }
        return cleaned.substring(0, maxLength - 3) + "...";
    }

    /**
     * 比较金额是否相等（考虑精度）
     * @param amount1 金额1
     * @param amount2 金额2
     * @return 是否相等
     */
    public static boolean amountEquals(BigDecimal amount1, BigDecimal amount2) {
        if (amount1 == null && amount2 == null) {
            return true;
        }
        if (amount1 == null || amount2 == null) {
            return false;
        }
        return formatAmount(amount1).compareTo(formatAmount(amount2)) == 0;
    }

    /**
     * 金额转换为字符串（格式化显示）
     * @param amount 金额
     * @return 字符串
     */
    public static String amountToString(BigDecimal amount) {
        if (amount == null) {
            return "0.00";
        }
        return formatAmount(amount).toString();
    }

    /**
     * 字符串转换为金额
     * @param amountStr 金额字符串
     * @return 金额
     * @throws NumberFormatException 格式错误时抛出异常
     */
    public static BigDecimal stringToAmount(String amountStr) {
        if (StrUtil.isBlank(amountStr)) {
            return BigDecimal.ZERO;
        }
        try {
            return new BigDecimal(cleanString(amountStr));
        } catch (NumberFormatException e) {
            throw new NumberFormatException("金额格式不正确: " + amountStr);
        }
    }
}
